#include "CFileScanner.h"
#include <string>
#include <cstring>

CFileScanner::CFileScanner()
    : _M_notify(nullptr), _M_b_stopped(true), _M_file_count(0), _M_dir_count(0) {
    pthread_mutex_init(&_M_lock, nullptr);
}

CFileScanner::~CFileScanner() {
    pthread_mutex_destroy(&_M_lock);
}

void CFileScanner::set_notify(_i_scan_notify* p) {
    _M_notify = p;
}

void CFileScanner::add_path(const char* lpszPath) {
    if (lpszPath != nullptr) {
		struct stat path_stat;
		if (stat(lpszPath, &path_stat) != 0) {
			return;
		}
		if( S_ISREG(path_stat.st_mode))
		{
			_M_file_count++;
			std::cout << "File111111: " << lpszPath << std::endl;
			return;
		}
		
        pthread_mutex_lock(&_M_lock);
        _M_dir_queue.push(lpszPath);
        pthread_mutex_unlock(&_M_lock);
    }
}

void CFileScanner::clear() {
    pthread_mutex_lock(&_M_lock);
    while (!_M_dir_queue.empty()) {
        _M_dir_queue.pop();
    }
    pthread_mutex_unlock(&_M_lock);
}

void CFileScanner::stop() {
    _M_b_stopped = true;
    clear();
}

bool CFileScanner::scan(bool recursive) {
    if (!_M_b_stopped) {
        return true;
    }

    std::string path;
    _M_b_stopped = false;
    _M_file_count = 0;
    _M_dir_count = 0;

    if (_M_notify != nullptr) {
        _M_notify->on_begin_scan();
    }

    while (!_M_b_stopped) {
        pthread_mutex_lock(&_M_lock);
        if (_M_dir_queue.empty()) {
            pthread_mutex_unlock(&_M_lock);
            break;
        }
        path = _M_dir_queue.front();
        _M_dir_queue.pop();
        pthread_mutex_unlock(&_M_lock);

        if (!scan(path.c_str(), recursive)) {
            break;
        }
    }

    _M_b_stopped = true;
    clear();

    if (_M_notify != nullptr) {
        _M_notify->on_end_scan();
    }

    return false;
}

bool CFileScanner::scan(const char* lpszPath, bool recursive) {
    if (lpszPath == nullptr) {
        return false;
    }

    DIR* dir = opendir(lpszPath);
    if (dir == nullptr) {
        return false;
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != nullptr && !_M_b_stopped) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        std::string fullPath = std::string(lpszPath) + "/" + entry->d_name;
        struct stat statbuf;
		memset(&statbuf, 0, sizeof(statbuf));
        if (stat(fullPath.c_str(), &statbuf) == 0) {
            if (S_ISDIR(statbuf.st_mode)) {
                _M_dir_count++;
                if (recursive) {
                    pthread_mutex_lock(&_M_lock);
                    _M_dir_queue.push(fullPath);
                    pthread_mutex_unlock(&_M_lock);
                }
                if (_M_notify != nullptr) {
                    _M_notify->on_directory(fullPath.c_str());
                }
            } else if (S_ISREG(statbuf.st_mode)) {
                _M_file_count++;
                if (_M_notify != nullptr) {
                    _M_notify->on_file(fullPath.c_str());
                }
            }
        }
    }

    closedir(dir);
    return true;
}

void* CFileScanner::ScanThreadFunc(void* arg) {
    CFileScanner* scanner = static_cast<CFileScanner*>(arg);
    scanner->scan(true);
    return nullptr;
}


bool CFileScanner::start_scan_thread(bool recursive) {
    if (!_M_b_stopped) {
        return true; // If already scanning, return immediately
    }

    _M_b_stopped = false;

    int result = pthread_create(&scan_thread, nullptr, ScanThreadFunc, this);
    if (result != 0) {
        _M_b_stopped = true;
        return false;
    }

    return true;
}